#pragma once

#include <sys/stat.h>
#include <cstdio>
#include <cassert>
#include <cctype>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <regex>
#include <functional>
#include <unordered_map>
#include <algorithm>
#include "./../log.hpp"
#include "./../server.hpp"

std::unordered_map<std::string, std::string> extMine {
    {".aac", "audio/aac"},
    {".abw", "application/x-abiword"},
    {".arc", "application/x-freearc"},
    {".avi", "video/x-msvideo"},
    {".azw", "application/vnd.amazon.ebook"},
    {".bin", "application/octet-stream"},
    {".bmp", "image/bmp"},
    {".bz", "application/x-bzip"},
    {".bz2", "application/x-bzip2"},
    {".csh", "application/x-csh"},
    {".css", "text/css"},
    {".csv", "text/csv"},
    {".doc", "application/msword"},
    {".docx", "application/vnd.openxmlformatsofficedocument.wordprocessingml.document"},
    {".eot", "application/vnd.ms-fontobject"},
    {".epub", "application/epub+zip"},
    {".gif", "image/gif"},
    {".htm", "text/html"},
    {".html", "text/html"},
    {".ico", "image/vnd.microsoft.icon"},
    {".ics", "text/calendar"},
    {".jar", "application/java-archive"},
    {".jpeg", "image/jpeg"},
    {".jpg", "image/jpeg"},
    {".js", "text/javascript"},
    {".json", "application/json"},
    {".jsonld", "application/ld+json"},
    {".mid", "audio/midi"},
    {".midi", "audio/x-midi"},
    {".mjs", "text/javascript"},
    {".mp3", "audio/mpeg"},
    {".mpeg", "video/mpeg"},
    {".mpkg", "application/vnd.apple.installer+xml"},
    {".odp", "application/vnd.oasis.opendocument.presentation"},
    {".ods", "application/vnd.oasis.opendocument.spreadsheet"},
    {".odt", "application/vnd.oasis.opendocument.text"},
    {".oga", "audio/ogg"},
    {".ogv", "video/ogg"},
    {".ogx", "application/ogg"},
    {".otf", "font/otf"},
    {".png", "image/png"},
    {".pdf", "application/pdf"},
    {".ppt", "application/vnd.ms-powerpoint"},
    {".pptx", "application/vnd.openxmlformatsofficedocument.presentationml.presentation"},
    {".rar", "application/x-rar-compressed"},
    {".rtf", "application/rtf"},
    {".sh", "application/x-sh"},
    {".svg", "image/svg+xml"},
    {".swf", "application/x-shockwave-flash"},
    {".tar", "application/x-tar"},
    {".tif", "image/tiff"},
    {".tiff", "image/tiff"},
    {".ttf", "font/ttf"},
    {".txt", "text/plain"},
    {".vsd", "application/vnd.visio"},
    {".wav", "audio/wav"},
    {".weba", "audio/webm"},
    {".webm", "video/webm"},
    {".webp", "image/webp"},
    {".woff", "font/woff"},
    {".woff2", "font/woff2"},
    {".xhtml", "application/xhtml+xml"},
    {".xls", "application/vnd.ms-excel"},
    {".xlsx", "application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet"},
    {".xml", "application/xml"},
    {".xul", "application/vnd.mozilla.xul+xml"},
    {".zip", "application/zip"},
    {".3gp", "video/3gpp"},
    {".3g2", "video/3gpp2"},
    {".7z", "application/x-7z-compressed"}
};

std::unordered_map<int, std::string> statuDesc {
    {100, "Continue"},
    {101, "Switching Protocol"},
    {102, "Processing"},
    {103, "Early Hints"},
    {200, "OK"},
    {201, "Created"},
    {202, "Accepted"},
    {203, "Non-Authoritative Information"},
    {204, "No Content"},
    {205, "Reset Content"},
    {206, "Partial Content"},
    {207, "Multi-Status"},
    {208, "Already Reported"},
    {226, "IM Used"},
    {300, "Multiple Choice"},
    {301, "Moved Permanently"},
    {302, "Found"},
    {303, "See Other"},
    {304, "Not Modified"},
    {305, "Use Proxy"},
    {306, "unused"},
    {307, "Temporary Redirect"},
    {308, "Permanent Redirect"},
    {400, "Bad Request"},
    {401, "Unauthorized"},
    {402, "Payment Required"},
    {403, "Forbidden"},
    {404, "Not Found"},
    {405, "Method Not Allowed"},
    {406, "Not Acceptable"},
    {407, "Proxy Authentication Required"},
    {408, "Request Timeout"},
    {409, "Conflict"},
    {410, "Gone"},
    {411, "Length Required"},
    {412, "Precondition Failed"},
    {413, "Payload Too Large"},
    {414, "URI Too Long"},
    {415, "Unsupported Media Type"},
    {416, "Range Not Satisfiable"},
    {417, "Expectation Failed"},
    {418, "I'm a teapot"},
    {421, "Misdirected Request"},
    {422, "Unprocessable Entity"},
    {423, "Locked"},
    {424, "Failed Dependency"},
    {425, "Too Early"},
    {426, "Upgrade Required"},
    {428, "Precondition Required"},
    {429, "Too Many Requests"},
    {431, "Request Header Fields Too Large"},
    {451, "Unavailable For Legal Reasons"},
    {501, "Not Implemented"},
    {502, "Bad Gateway"},
    {503, "Service Unavailable"},
    {504, "Gateway Timeout"},
    {505, "HTTP Version Not Supported"},
    {506, "Variant Also Negotiates"},
    {507, "Insufficient Storage"},
    {508, "Loop Detected"},
    {510, "Not Extended"},
    {511, "Network Authentication Required"}
};

class Util
{
public:
    // 字符串切割
    static size_t Split(const std::string& str, const std::string& sep, std::vector<std::string>* vec)
    {
        size_t pos = 0;
        while (pos < str.size())
        {
            size_t iter = str.find(sep, pos);
            if (iter == std::string::npos) {
                // "If this is equal to the string length, the function returns an empty string."
                vec->push_back(str.substr(pos));
                return vec->size();
            }
            else {
                if (iter - pos != 0) {
                    vec->push_back(str.substr(pos, iter - pos));
                }
            }
            pos = iter + sep.size();
        }
        return vec->size();
    }

    static bool ReadFile(const std::string filename, std::string* buf)
    {
        // 以二进制读方式打开文件 保持文件原有内容
        std::ifstream ifs(filename, std::ios::binary);
        if (!ifs.is_open()) {
            printf("OPEN FILE ERR: %s", filename.c_str());
            ifs.close();
            return false;
        }
        ifs.seekg(0, ifs.end);
        size_t fsize = ifs.tellg();
        ifs.seekg(0, ifs.beg);
        buf->resize(fsize);
        ifs.read(&((*buf)[0]), fsize);
        if (!ifs.good()) {
            printf("READ FILE ERR: %s", filename.c_str());
            ifs.close();
            return false;
        }
        ifs.close();
        return true;
    }

    static bool WriteFile(const std::string filename, const std::string& buf)
    {
        // 二进制覆盖写入
        std::ofstream ofs(filename, std::ios::binary | std::ios::trunc);
        if (!ofs.is_open()) {
            printf("OPEN FILE ERR: %s", filename.c_str());
            ofs.close();
            return false;
        }
        ofs.write(buf.c_str(), buf.size());
        if (!ofs.good()) {
            printf("WRITE FILE ERR: %s", filename.c_str());
            ofs.close();
            return false;
        }
        ofs.close();
        return true;
    }

    static std::string UrlEncode(const std::string& url, bool convert_space_to_plus = false)
    {
        std::string res;
        for (const auto& ch : url)
        {
            if (ch == '.' || ch == '-' || ch == '_' || ch == '~' || isalnum(ch)) {
                res += ch;
            }
            else if (ch == ' ' && convert_space_to_plus) {
                res += '+';
            }
            else {
                char tmp[4] = { 0 };
                snprintf(tmp, 4, "%%%02X", ch);
                res += tmp;
            }
        }
        return res;
    }

    static char HexToI(char ch)
    {
        if (ch >= '0' && ch <= '9') {
            return ch - '0';
        }
        else if (ch >= 'a' && ch <= 'z') {
            return ch - 'a' + 10;
        }
        else if (ch >= 'A' && ch <= 'Z') {
            return ch - 'A' + 10;
        }
        else { // err
            return -1;
        }
    }

    static std::string UrlDecode(const std::string& url, bool convert_plus_to_space = false)
    {
        std::string res;
        int i = 0;
        while (i < url.size())
        {
            if (url[i] == '+' && convert_plus_to_space) {
                res += ' '; ++i;
            }
            else if (url[i] == '%' && (i + 2) < url.size()) {
                char p1 = HexToI(url[i + 1]);
                char p2 = HexToI(url[i + 2]);
                res += (p1 << 4) + p2;
                i += 3;
            }
            else {
                res += url[i]; ++i;
            }
        }
        return res;
    }

    static std::string Mine(const std::string& filename)
    {
        size_t pos = filename.rfind('.');
        if (pos == std::string::npos) {
            return "application/octet-stream";
        }
        auto iter = extMine.find(filename.substr(pos));
        if (iter == extMine.end()) {
            return "application/octet-stream";
        }
        else {
            return iter->second;
        }
    }

    static std::string Statu(int statu_num)
    {
        auto iter = statuDesc.find(statu_num);
        if (iter == statuDesc.end()) {
            return "Unknown";
        }
        else {
            return iter->second;
        }
    }

    static bool IsDirectory(const std::string& filename)
    {
        struct stat fileSt;
        if (stat(filename.c_str(), &fileSt) < 0) {
            return false;
        }
        // stat.h:#define S_ISDIR(m)	(((m) & S_IFMT) == S_IFDIR)
        return S_ISDIR(fileSt.st_mode);
    }

    static bool IsRegular(const std::string& filename)
    {
        struct stat fileSt;
        if (stat(filename.c_str(), &fileSt) < 0) {
            return false;
        }
        // stat.h:#define S_ISREG(m)	(((m) & S_IFMT) == S_IFREG)
        return S_ISREG(fileSt.st_mode);
    }

    static bool LegalPath(const std::string& path)
    {
        std::vector<std::string> subStrs;
        Split(path, "/", &subStrs);
        int level = 0;
        for (const auto& str : subStrs) {
            if (str == "..") {
                --level;
                if (level < 0) { return false; }
            }
            else {
                ++level;
            }
        }
        return true;
    }
};

class HttpRequest
{
public:
    void SetHeader(const std::string& key, const std::string& val)
    {
        _headers.insert(std::make_pair(key, val));
    }

    bool HasHeader(const std::string& key) const
    {
        return (_headers.find(key) != _headers.end());
    }

    const std::string GetHeader(const std::string& key) const
    {
        if (!HasHeader(key)) { return ""; }
        else { return (_headers.find(key))->second; }
    }

    void SetParam(const std::string& key, const std::string& val)
    {
        _params.insert(std::make_pair(key, val));
    }
    
    bool HasParam(const std::string& key) const
    {
        return (_params.find(key) != _params.end());
    }

    const std::string GetParam(const std::string& key) const
    {
        if (!HasParam(key)) { return ""; }
        else { return (_params.find(key))->second; }
    }

    size_t ContentLength()
    {
        if (!HasHeader("Content-Length")) { return 0; }
        return std::stol(GetHeader("Content-Length"));
    }
    
    bool Close() const
    {
        if (HasHeader("Connection") && GetHeader("Connection") == "keep-alive") {
            return false;
        }
        return true;
    }

    void Reset()
    {
        _method.clear();
        _path.clear();
        _version.clear();
        _body.clear();
        std::smatch match;
        _match.swap(match);
        _headers.clear();
        _params.clear();
    }

public:
    std::string _method;
    std::string _path;
    std::string _version;
    std::string _body;
    std::smatch _match;
    std::unordered_map<std::string, std::string> _headers;
    std::unordered_map<std::string, std::string> _params;
};

class HttpResponse
{
public:
    HttpResponse(int statu = 200)
        :_statu(statu), _redirect(false)
    {}

    void SetContent(const std::string& content, const std::string& type = "text/html")
    {
        _body = content;
        SetHeader("Content-Type", type);
        // Content-Length头部字段：在组织响应时添加
    }

    void SetHeader(const std::string& key, const std::string& val)
    {
        _headers.insert(std::make_pair(key, val));
    }

    bool HasHeader(const std::string& key) const
    {
        return (_headers.find(key) != _headers.end());
    }

    std::string GetHeader(const std::string& key) const
    {
        if (!HasHeader(key)) { return ""; }
        else { return _headers.find(key)->second; }
    }
    
    bool Close() const
    {
        if (HasHeader("Connection") && GetHeader("Connection") == "keep-alive") {
            return false;
        }
        return true;
    }

    void SetRedirect(const std::string& url, int statu = 302)
    {
        _statu = statu;
        _redirect = true;
        _redirect_url = url;
        // Redirection头部字段：在组织响应时添加
    }

    void Reset()
    {
        _statu = 200;
        _body.clear();
        _redirect = false;
        _redirect_url.clear();
        _headers.clear();
    }

public:
    int _statu;
    std::string _body;
    bool _redirect;
    std::string _redirect_url;
    std::unordered_map<std::string, std::string> _headers;
};

enum HttpRecvStat
{
    HTTP_RECV_LINE,
    HTTP_RECV_HEAD,
    HTTP_RECV_BODY,
    HTTP_RECV_OVER,
    HTTP_RECV_ERR
};

const int MAX_LINE_SIZE = 8096;

class HttpContext
{
public:
    HttpContext()
        :_recv_stat(HTTP_RECV_LINE),
        _resp_statu(200)
    { }

    int RespStatu() {
        return _resp_statu;
    }

    HttpRecvStat RecvStat() {
        return _recv_stat;
    }

    void RecvHttpReq(Buffer* buf)
    {
        // 根据不同的接收状态进行处理
        // RecvHttpLine之后要继续RecvHttpHead，不能break
        switch (_recv_stat)
        {
            case HTTP_RECV_LINE: RecvHttpLine(buf);
            case HTTP_RECV_HEAD: RecvHttpHead(buf);
            case HTTP_RECV_BODY: RecvHttpBody(buf);
        };
    }

    HttpRequest& Request() {
        return _request;
    }

    void Reset()
    {
        _recv_stat = HTTP_RECV_LINE;
        _resp_statu = 200;
        _request.Reset();
    }

private:
    bool RecvHttpLine(Buffer* buf)
    {
        if (_recv_stat != HTTP_RECV_LINE) { return false; }
        std::string line = buf->GetLineAndPop();
        // 不足一行
        if (line.size() == 0)
        {
            if (buf->GetReadableSpace() > MAX_LINE_SIZE) {
                _recv_stat = HTTP_RECV_ERR;
                _resp_statu = 414; // "URI Too Long"
            }
            return true; // 继续接收请求
        }
        // 长度不合理
        if (line.size() > MAX_LINE_SIZE) {
            _recv_stat = HTTP_RECV_ERR;
            _resp_statu = 414; // "URI Too Long"
            return false;
        }
        _recv_stat = HTTP_RECV_HEAD;
        return ParseHttpLine(line);
    }

    bool ParseHttpLine(const std::string& line)
    {
        // e.g.:
        // 0:GET /havefun/login?usr=shr&passwd=666 HTTP/1.0
        // 1:GET
        // 2:/havefun/login
        // 3:usr=shr&passwd=666
        // 4:HTTP/1.0
        std::smatch sm;
        // 忽略大小写匹配
        std::regex reg("(GET|POST|HEAD|DELETE|PUT) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?", std::regex::icase);
        bool ret = std::regex_match(line, sm, reg);
        if (!ret) {
            _recv_stat = HTTP_RECV_ERR;
            _resp_statu = 400; // "Bad Request"
            return false;
        }
        _request._method = sm[1];
        // 将请求字段统一置为大写
        std::transform(_request._method.begin(), _request._method.end(), _request._method.begin(), toupper);
        // 对请求路径进行正常解码
        _request._path = Util::UrlDecode(sm[2]);
        _request._version = sm[4];
        std::vector<std::string> queries;
        Util::Split(sm[3], "&", &queries);
        for (const auto& query : queries)
        {
            size_t pos = query.find('=');
            if (pos == std::string::npos) {
                _recv_stat = HTTP_RECV_ERR;
                _resp_statu = 400; // "Bad Request"
                return false;
            }
            // 对查询字符串按照w3c标准进行解码
            std::string key = Util::UrlDecode(query.substr(0, pos), true);
            std::string val = Util::UrlDecode(query.substr(pos + 1), true);
            _request.SetParam(key, val);
        }
        return true;
    }

    bool RecvHttpHead(Buffer* buf)
    {
        if (_recv_stat != HTTP_RECV_HEAD) { return false; }
        // key: val\r\nkey: val\r\n
        // 逐行读取，逐行解析
        while (true)
        {
            std::string headLine = buf->GetLineAndPop();
            // 遇到空行结束
            if (headLine == "\r\n" || headLine == "\n") {
                break;
            }
            // 不足一行
            if (headLine.size() == 0)
            {
                if (buf->GetReadableSpace() > MAX_LINE_SIZE) {
                    _recv_stat = HTTP_RECV_ERR;
                    _resp_statu = 400; // "Bad Request"
                }
                return true; // 继续接收请求
            }
            // 长度不合理
            if (headLine.size() > MAX_LINE_SIZE) {
                _recv_stat = HTTP_RECV_ERR;
                _resp_statu = 400; // "Bad Request"
                return false;
            }
            bool ret = ParseHttpHead(headLine);
            if (!ret) { return false; }
        }
        _recv_stat = HTTP_RECV_BODY;
        return true;
    }

    bool ParseHttpHead(std::string& headLine)
    {
        if (headLine.back() == '\n') { headLine.pop_back(); }
        if (headLine.back() == '\r') { headLine.pop_back(); }
        // key: val
        size_t pos = headLine.find(": ");
        if (pos == std::string::npos) {
            _recv_stat = HTTP_RECV_ERR;
            _resp_statu = 400; // "Bad Request"
            return false;
        }
        std::string key = headLine.substr(0, pos);
        std::string val = headLine.substr(pos + 2);
        _request.SetHeader(key, val);
        return true;
    }

    bool RecvHttpBody(Buffer* buf)
    {
        if (_recv_stat != HTTP_RECV_BODY) {
            return false;
        }
        size_t contentLength = _request.ContentLength();
        // 没有正文，直接结束Recv并返回
        if (contentLength == 0) {
            _recv_stat = HTTP_RECV_OVER;
            return true;
        }
        // 当前需要的正文长度
        size_t neededLength = contentLength - _request._body.size();
        // 缓冲区的内容足够:读取所需长度，并结束Recv
        if (buf->GetReadableSpace() >= neededLength) {
            _request._body += buf->ReadAndPop(neededLength);
            _recv_stat = HTTP_RECV_OVER;
            return true;
        }
        // 缓冲区的内容不够:读完并等待下次Recv
        else {
            _request._body += buf->ReadAndPop(buf->GetReadableSpace());
            return true;
        }
    }

private:
    HttpRecvStat _recv_stat;
    int _resp_statu; // 响应状态码
    HttpRequest _request; // 解析后的HttpRequest
};

const int DEFAULT_TIMEOUT = 30;

class HttpServer
{
private:
    using handler = std::function<void(const HttpRequest&, HttpResponse*)>;
    // 正则表达式 - 处理方法
    using handlers = std::vector<std::pair<std::regex, handler>>;

public:
    HttpServer(int port, int timeout = DEFAULT_TIMEOUT)
        :_server(port)
    {
        _server.InactiveReleaseEnable(timeout); // 默认开启超时连接关闭
        _server.SetConnectedCb(std::bind(&HttpServer::OnConnectd, this, std::placeholders::_1));
        _server.SetMessageCb(std::bind(&HttpServer::OnMessage, this, std::placeholders::_1, std::placeholders::_2));
    }

    void Get(const std::string& pattern, const handler& hd) {
        _get_route.push_back(std::make_pair(std::regex(pattern), hd));
    }

    void Post(const std::string& pattern, const handler& hd) {
        _post_route.push_back(std::make_pair(std::regex(pattern), hd));
    }

    void Put(const std::string& pattern, const handler& hd) {
        _put_route.push_back(std::make_pair(std::regex(pattern), hd));
    }

    void Delete(const std::string& pattern, const handler& hd) {
        _delete_route.push_back(std::make_pair(std::regex(pattern), hd));
    }

    void SetThreadCount(int count) {
        _server.SetThreadCount(count);
    }

    void SetBaseDir(const std::string& base_dir)
    {
        assert(Util::IsDirectory(base_dir));
        _base_dir = base_dir;
    }

    void Start() {
        _server.Start();
    }

private:
    // 设置连接上下文
    void OnConnectd(const PtrConnection& conn)
    {
        conn->SetContext(HttpContext());
        // ns_log::lg(ns_log::LOG, "ON CONNECTED...");
        std::cout << "ON CONNECTED:" << conn.get() << std::endl;
    }

    void ErrHandler(HttpResponse* res)
    {
        std::string body;
        body += "<html>";
        body += "<head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"></head>";
        body += "<h1>";
        body += std::to_string(res->_statu);
        body += " ";
        body += Util::Statu(res->_statu);
        body += "</h1>";
        body += "</html>";
        res->SetContent(body, "text/html");
    }

    void OnMessage(const PtrConnection& conn, Buffer* buf)
    {
        while (!buf->Empty())
        {
            HttpContext* context = conn->GetContext()->Get<HttpContext>();
            context->RecvHttpReq(buf);
            HttpResponse res(context->RespStatu());
            // RecvHttpReq出错
            if (res._statu >= 400) {
                HttpRequest err_req;
                err_req._version = "HTTP/1.0";
                ErrHandler(&res); //组织err信息
                ResponseWrite(conn, err_req, res);
                context->Reset(); // 重置上下文状态
                buf->Clear(); // 清空缓冲区
                conn->ShutDown();
                return;
            }
            // RecvHttpReq数据不全 -> 继续接收
            if (context->RecvStat() != HTTP_RECV_OVER) {
                return;
            }
            HttpRequest& req = context->Request();
            Route(req, &res);
            ResponseWrite(conn, req, res);
            // 重置上下文,避免影响下次处理
            context->Reset();
            // 短连接直接关闭
            if (res.Close()) { conn->ShutDown(); }
        }
    }

    bool IsFileHandler(const HttpRequest& req)
    {
        if (req._method != "GET" && req._method != "HEAD") {
            return false;
        }
        if (req._path.empty()) {
            return false;
        }
        if (!Util::LegalPath(req._path)) {
            return false;
        }
        // 路径拼接
        std::string req_path = _base_dir + req._path;
        if (req_path.back() == '/') {
            req_path += "index.html";
        }
        if (!Util::IsRegular(req_path)) {
            return false;
        }
        return true;
    }
    // 静态资源请求处理
    void FileHandler(const HttpRequest& req, HttpResponse* res)
    {
        std::string req_path = _base_dir + req._path;
        if (req_path.back() == '/') {
            req_path += "index.html";
        }
        if (!Util::ReadFile(req_path, &(res->_body))) {
            return;
        }
        // HEAD请求不包含Content
        if (req._method != "HEAD") {
            std::string mine = Util::Mine(req_path);
            res->SetHeader("Content-Type", mine);
        }
    }
    // 功能请求分类处理
    void Dispatcher(HttpRequest& req, HttpResponse* res, handlers& hdrs)
    {
        for (const auto& hdr : hdrs)
        {
            const std::regex& reg = hdr.first;
            const handler& func = hdr.second;
            // 如果能匹配成功则执行对应回调
            if(std::regex_match(req._path, req._match, reg)) {
                return func(req, res);
            }
        }
        res->_statu = 405;
    }

    // 请求类型判断
    void Route(HttpRequest& req, HttpResponse* res)
    {
        if (IsFileHandler(req)) {
            return FileHandler(req, res);
        }
        if (req._method == "GET" || req._method == "HEAD") {
            return Dispatcher(req, res, _get_route);
        }
        if (req._method == "POST") {
            return Dispatcher(req, res, _post_route);
        }
        if (req._method == "PUT") {
            return Dispatcher(req, res, _put_route);
        }
        if (req._method == "DELETE") {
            return Dispatcher(req, res, _delete_route);
        }
        res->_statu = 405; // Method Not Allowed
    }
    // Response 组织和发送
    void ResponseWrite(const PtrConnection& conn, HttpRequest& req, HttpResponse& res)
    {
        // 添加头部字段
        if (req.Close()) {
            res.SetHeader("Connection", "close");
        }
        else {
            res.SetHeader("Connection", "keep-alive");
        }
        if (!res._body.empty() && !res.HasHeader("Content-Length")) {
            res.SetHeader("Content-Length", std::to_string(res._body.size()));
        }
        if (!res._body.empty() && !res.HasHeader("Content-Type")) {
            res.SetHeader("Content-Type", "application/octet-stream");
        }
        if (res._redirect) {
            res.SetHeader("Location", res._redirect_url);
        }
        // 组织http response
        std::stringstream resStr;
        resStr << req._version << " " << std::to_string(res._statu) << " " << Util::Statu(res._statu) << "\r\n";
        for (const auto& head : res._headers) {
            resStr << head.first << ": " << head.second << "\r\n";
        }
        resStr << "\r\n";
        resStr << res._body;
        // 发送
        conn->Send(resStr.str().c_str(), resStr.str().size());
    }

private:
    handlers _get_route;
    handlers _post_route;
    handlers _put_route;
    handlers _delete_route;
    std::string _base_dir;
    TcpServer _server;
};